#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
视力检查报告PDF导出服务
提供医院标准格式的视力检查报告PDF生成功能
"""

from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm, mm
from reportlab.lib import colors
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, Image, PageBreak
from reportlab.platypus.tableofcontents import TableOfContents
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT
from reportlab.pdfgen import canvas
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
import io
import os
from datetime import datetime
from typing import Dict, Any, Optional, List

class VisionReportPDFGenerator:
    """视力检查报告PDF生成器"""
    
    def __init__(self, export_config: Dict[str, Any]):
        """
        初始化PDF生成器
        
        Args:
            export_config: 从constants_v2.py获取的VISION_EXPORT_CONFIG['pdf']配置
        """
        self.config = export_config
        self.styles = getSampleStyleSheet()
        self._setup_fonts()
        self._setup_custom_styles()
    
    def _setup_fonts(self):
        """设置中文字体"""
        try:
            # 尝试注册中文字体
            font_paths = [
                '/System/Library/Fonts/PingFang.ttc',  # macOS
                'C:\\Windows\\Fonts\\simsun.ttc',       # Windows 宋体
                'C:\\Windows\\Fonts\\simhei.ttf',       # Windows 黑体
                '/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf'  # Linux
            ]
            
            for font_path in font_paths:
                if os.path.exists(font_path):
                    pdfmetrics.registerFont(TTFont('Chinese', font_path))
                    break
            else:
                print("警告: 未找到中文字体文件，使用默认字体")
        except Exception as e:
            print(f"字体注册失败: {e}")
    
    def _setup_custom_styles(self):
        """设置自定义样式"""
        # 标题样式
        self.title_style = ParagraphStyle(
            'CustomTitle',
            parent=self.styles['Title'],
            fontSize=18,
            fontName='Chinese',
            alignment=TA_CENTER,
            spaceAfter=20,
            textColor=colors.darkblue
        )
        
        # 副标题样式
        self.subtitle_style = ParagraphStyle(
            'CustomSubtitle',
            parent=self.styles['Heading2'],
            fontSize=14,
            fontName='Chinese',
            alignment=TA_CENTER,
            spaceAfter=15,
            textColor=colors.black
        )
        
        # 章节标题样式 - 去除边框
        self.section_style = ParagraphStyle(
            'CustomSection',
            parent=self.styles['Heading3'],
            fontSize=12,
            fontName='Chinese',
            alignment=TA_LEFT,
            spaceAfter=10,
            spaceBefore=15,
            textColor=colors.darkblue
        )
        
        # 正文样式
        self.normal_style = ParagraphStyle(
            'CustomNormal',
            parent=self.styles['Normal'],
            fontSize=10,
            fontName='Chinese',
            alignment=TA_LEFT,
            spaceAfter=6
        )
        
        # 数据样式
        self.data_style = ParagraphStyle(
            'CustomData',
            parent=self.styles['Normal'],
            fontSize=11,
            fontName='Chinese',
            alignment=TA_CENTER
        )
    
    def _has_data(self, obj: Any, field_name: str) -> bool:
        """检查字段是否有有效数据"""
        try:
            value = getattr(obj, field_name, None)
            if value is None:
                return False
            if isinstance(value, str) and value.strip() == '':
                return False
            return True
        except Exception:
            return False
    
    def generate_report(self, student: Any, record: Any, output_path: Optional[str] = None) -> io.BytesIO:
        """
        生成视力检查报告PDF
        
        Args:
            student: 学生信息对象
            record: 视力记录对象
            output_path: 输出文件路径（可选，默认返回BytesIO）
            
        Returns:
            BytesIO: PDF文件的字节流
        """
        # 创建PDF文档
        if output_path:
            doc = SimpleDocTemplate(output_path, pagesize=A4)
        else:
            buffer = io.BytesIO()
            doc = SimpleDocTemplate(buffer, pagesize=A4)
        
        # 构建文档内容
        story = []
        
        # 1. 报告头部
        story.extend(self._build_header())
        
        # 2. 患者信息
        story.extend(self._build_patient_info(student))
        
        # 3. 检查信息
        story.extend(self._build_exam_info(record))
        
        # 4. 视力数据
        story.extend(self._build_vision_data(record))
        
        # 5. 检查结论
        story.extend(self._build_conclusion(record))
        
        # 6. 报告尾部
        story.extend(self._build_footer())
        
        # 生成PDF
        doc.build(story)
        
        if output_path:
            return None
        else:
            buffer.seek(0)
            return buffer
    
    def _build_header(self) -> List[Any]:
        """构建报告头部"""
        elements = []
        header_config = self.config.get('header', {})
        
        # 医院标题
        hospital_name = header_config.get('hospital_name', '视力检查中心')
        elements.append(Paragraph(hospital_name, self.title_style))
        
        # 科室名称
        department = header_config.get('department', '眼科检查中心')
        elements.append(Paragraph(department, self.subtitle_style))
        
        # 报告标题
        report_title = self.config.get('title', '视力检查报告')
        elements.append(Paragraph(report_title, self.section_style))
        
        elements.append(Spacer(1, 15))
        
        return elements
    
    def _build_patient_info(self, student: Any) -> List[Any]:
        """构建患者信息部分 - 只显示有数据的项目"""
        elements = []
        
        # 章节标题
        elements.append(Paragraph("患者基本信息", self.section_style))
        
        # 患者信息表格 - 过滤空数据
        patient_fields = self.config.get('patient_info_fields', [])
        valid_fields = []
        
        for field in patient_fields:
            field_name = field['field']
            if self._has_data(student, field_name):
                valid_fields.append(field)
        
        if not valid_fields:
            elements.append(Paragraph("无患者信息", self.normal_style))
            elements.append(Spacer(1, 15))
            return elements
        
        patient_data = []
        
        # 将有效字段按2列排列
        for i in range(0, len(valid_fields), 2):
            row = []
            
            # 左列
            if i < len(valid_fields):
                field = valid_fields[i]
                field_name = field['field']
                display_name = field['display_name']
                value = self._get_field_value(student, field_name)
                row.extend([display_name + ':', value])
            else:
                row.extend(['', ''])
            
            # 右列
            if i + 1 < len(valid_fields):
                field = valid_fields[i + 1]
                field_name = field['field']
                display_name = field['display_name']
                value = self._get_field_value(student, field_name)
                row.extend([display_name + ':', value])
            else:
                row.extend(['', ''])
            
            patient_data.append(row)
        
        # 创建表格
        if patient_data:
            table = Table(patient_data, colWidths=[3*cm, 4*cm, 3*cm, 4*cm])
            table.setStyle(TableStyle([
                ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
                ('FONTNAME', (0, 0), (-1, -1), 'Chinese'),
                ('FONTSIZE', (0, 0), (-1, -1), 10),
                ('GRID', (0, 0), (-1, -1), 0.5, colors.grey),
                ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
                ('BACKGROUND', (0, 0), (-1, -1), colors.lightgrey)
            ]))
            elements.append(table)
        
        elements.append(Spacer(1, 15))
        return elements
    
    def _build_exam_info(self, record: Any) -> List[Any]:
        """构建检查信息部分 - 只显示有数据的项目"""
        elements = []
        
        # 章节标题
        elements.append(Paragraph("检查信息", self.section_style))
        
        # 检查信息表格 - 过滤空数据
        exam_fields = self.config.get('exam_info_fields', [])
        valid_fields = []
        
        for field in exam_fields:
            field_name = field['field']
            if self._has_data(record, field_name):
                valid_fields.append(field)
        
        if not valid_fields:
            elements.append(Paragraph("无检查信息", self.normal_style))
            elements.append(Spacer(1, 15))
            return elements
        
        exam_data = []
        
        for i in range(0, len(valid_fields), 2):
            row = []
            
            # 左列
            if i < len(valid_fields):
                field = valid_fields[i]
                field_name = field['field']
                display_name = field['display_name']
                value = self._get_field_value(record, field_name)
                row.extend([display_name + ':', value])
            else:
                row.extend(['', ''])
            
            # 右列
            if i + 1 < len(valid_fields):
                field = valid_fields[i + 1]
                field_name = field['field']
                display_name = field['display_name']
                value = self._get_field_value(record, field_name)
                row.extend([display_name + ':', value])
            else:
                row.extend(['', ''])
            
            exam_data.append(row)
        
        if exam_data:
            table = Table(exam_data, colWidths=[3*cm, 4*cm, 3*cm, 4*cm])
            table.setStyle(TableStyle([
                ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
                ('FONTNAME', (0, 0), (-1, -1), 'Chinese'),
                ('FONTSIZE', (0, 0), (-1, -1), 10),
                ('GRID', (0, 0), (-1, -1), 0.5, colors.grey),
                ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
                ('BACKGROUND', (0, 0), (-1, -1), colors.lightblue)
            ]))
            elements.append(table)
        
        elements.append(Spacer(1, 15))
        return elements
    
    def _build_vision_data(self, record: Any) -> List[Any]:
        """构建视力数据部分 - 只显示有数据的项目"""
        elements = []
        
        # 章节标题
        elements.append(Paragraph("视力检查数据", self.section_style))
        
        # 处理各个视力数据部分
        vision_sections = self.config.get('vision_data_sections', [])
        has_any_data = False
        
        for section_config in vision_sections:
            section_name = section_config.get('section', '')
            section_fields = section_config.get('fields', [])
            
            if not section_fields:
                continue
            
            # 过滤有数据的字段
            valid_fields = []
            for field in section_fields:
                field_name = field['field']
                if self._has_data(record, field_name):
                    valid_fields.append(field)
            
            if not valid_fields:
                continue
            
            has_any_data = True
            
            # 小节标题
            elements.append(Paragraph(section_name, self.normal_style))
            
            # 创建数据表格
            data = [['项目', '数值', '单位']]
            
            for field in valid_fields:
                field_name = field['field']
                display_name = field['display_name']
                value = self._get_field_value(record, field_name)
                unit = self._get_field_unit(field_name)
                
                data.append([display_name, str(value), unit])
            
            table = Table(data, colWidths=[4*cm, 3*cm, 2*cm])
            table.setStyle(TableStyle([
                ('BACKGROUND', (0, 0), (-1, 0), colors.grey),
                ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
                ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
                ('FONTNAME', (0, 0), (-1, -1), 'Chinese'),
                ('FONTSIZE', (0, 0), (-1, -1), 10),
                ('GRID', (0, 0), (-1, -1), 0.5, colors.black),
                ('VALIGN', (0, 0), (-1, -1), 'MIDDLE')
            ]))
            elements.append(table)
            elements.append(Spacer(1, 10))
        
        if not has_any_data:
            elements.append(Paragraph("暂无视力检查数据", self.normal_style))
            elements.append(Spacer(1, 15))
        
        return elements
    
    def _build_conclusion(self, record: Any) -> List[Any]:
        """构建检查结论部分 - 只显示有数据的项目"""
        elements = []
        
        # 章节标题
        elements.append(Paragraph("检查结论", self.section_style))
        
        # 结论字段 - 过滤空数据
        conclusion_fields = self.config.get('conclusion_fields', [])
        conclusion_data = []
        
        for field in conclusion_fields:
            field_name = field['field']
            display_name = field['display_name']
            
            if self._has_data(record, field_name):
                value = self._get_field_value(record, field_name)
                conclusion_data.append([display_name + ':', str(value)])
        
        if conclusion_data:
            table = Table(conclusion_data, colWidths=[4*cm, 10*cm])
            table.setStyle(TableStyle([
                ('ALIGN', (0, 0), (0, -1), 'RIGHT'),
                ('ALIGN', (1, 0), (1, -1), 'LEFT'),
                ('FONTNAME', (0, 0), (-1, -1), 'Chinese'),
                ('FONTSIZE', (0, 0), (-1, -1), 10),
                ('VALIGN', (0, 0), (-1, -1), 'TOP'),
                ('LEFTPADDING', (0, 0), (-1, -1), 10),
                ('RIGHTPADDING', (0, 0), (-1, -1), 10),
                ('TOPPADDING', (0, 0), (-1, -1), 5),
                ('BOTTOMPADDING', (0, 0), (-1, -1), 5)
            ]))
            elements.append(table)
        else:
            elements.append(Paragraph("暂无检查结论", self.normal_style))
        
        elements.append(Spacer(1, 15))
        return elements
    
    def _build_footer(self) -> List[Any]:
        """构建报告尾部"""
        elements = []
        
        footer_config = self.config.get('footer', {})
        
        # 签名行
        signature_line = footer_config.get('signature_line', '检查医师签名：_______________')
        elements.append(Paragraph(signature_line, self.normal_style))
        elements.append(Spacer(1, 10))
        
        # 日期行
        date_line = footer_config.get('date_line', '报告日期：_______________')
        current_date = datetime.now().strftime('%Y年%m月%d日')
        date_line = date_line.replace('_______________', current_date)
        elements.append(Paragraph(date_line, self.normal_style))
        elements.append(Spacer(1, 10))
        
        # 医院印章位置
        hospital_seal = footer_config.get('hospital_seal', '医院印章')
        elements.append(Paragraph(f"[{hospital_seal}位置]", self.normal_style))
        
        return elements
    
    def _get_field_value(self, obj: Any, field_name: str) -> str:
        """获取对象字段值"""
        try:
            value = getattr(obj, field_name, '')
            if value is None:
                return ''
            
            # 特殊字段格式化
            if field_name in ['measure_date', 'birthday'] and hasattr(value, 'strftime'):
                return value.strftime('%Y-%m-%d')
            elif field_name == 'measure_time' and hasattr(value, 'strftime'):
                return value.strftime('%H:%M')
            elif field_name == 'age':
                # 计算年龄
                if hasattr(obj, 'birthday') and obj.birthday:
                    today = datetime.now().date()
                    birthday = obj.birthday
                    age = today.year - birthday.year
                    if today < birthday.replace(year=today.year):
                        age -= 1
                    return str(age)
                return ''
            
            return str(value)
        except Exception:
            return ''
    
    def _get_field_unit(self, field_name: str) -> str:
        """获取字段单位"""
        units = {
            'right_eye_naked': '',
            'left_eye_naked': '',
            'right_eye_corrected': '',
            'left_eye_corrected': '',
            'right_sphere': 'D',
            'left_sphere': 'D',
            'right_cylinder': 'D',
            'left_cylinder': 'D',
            'right_axis': '°',
            'left_axis': '°',
            'right_se': 'D',
            'left_se': 'D',
            'right_axial_length': 'mm',
            'left_axial_length': 'mm'
        }
        return units.get(field_name, '')

def create_vision_pdf_report(student: Any, record: Any, export_config: Dict[str, Any]) -> io.BytesIO:
    """
    创建视力检查PDF报告的便捷函数
    
    Args:
        student: 学生信息对象
        record: 视力记录对象  
        export_config: PDF导出配置
        
    Returns:
        BytesIO: PDF文件的字节流
    """
    try:
        generator = VisionReportPDFGenerator(export_config)
        return generator.generate_report(student, record)
    except ImportError:
        raise ImportError("PDF生成需要安装reportlab库: pip install reportlab")
    except Exception as e:
        raise Exception(f"PDF生成失败: {str(e)}")
